package com.example.spider.task.limit;

import cn.hutool.core.util.ReflectUtil;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializerProvider;
import lombok.SneakyThrows;
import org.shoulder.core.util.JsonUtils;

import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

/**
 *
 * @author lym
 */
public class LimitStrategyJsonSerializer extends JsonSerializer<LimitStrategy> {

    public static final String TYPE = "TYPE";

    public static final String OBJ = "OBJ";

    private final ObjectMapper mapper = new ObjectMapper();

    @SneakyThrows
    @Override
    public void serialize(LimitStrategy limitStrategy, JsonGenerator generator, SerializerProvider serializerProvider) throws IOException {
        if (limitStrategy == null) {
            generator.writeString("null");
            return;
        }

        generator.writeStartObject();
        generator.writeFieldName("TYPE");
        LimitStrategyEnum limitStrategyEnum = LimitStrategyEnum.valueOfType(limitStrategy.getClass());
        generator.writeString(limitStrategyEnum.name());
        Field[] fieldArr = ReflectUtil.getFields(limitStrategyEnum.getType(), f -> {
            int modifiers = f.getModifiers();
            return !Modifier.isFinal(modifiers) && !Modifier.isStatic(modifiers) && !Modifier.isTransient(modifiers);
        });
        for (Field field : fieldArr) {
            generator.writeFieldName(field.getName());
            if (field.canAccess(limitStrategy)) {
                Object value = field.get(limitStrategy);
                if (Enum.class.isAssignableFrom(field.getType())) {
                    generator.writeString(((Enum<?>) value).name());
                } else if (CharSequence.class.isAssignableFrom(field.getType())) {
                    generator.writeString((String) value);
                } else {
                    generator.writeString(JsonUtils.toJson(value));
                }
            } else {
                Method getter = ReflectUtil.getMethodByName(limitStrategyEnum.getType(), true, "get" + field.getName());
                Object value = getter.invoke(limitStrategy);
                if (Enum.class.isAssignableFrom(getter.getReturnType())) {
                    generator.writeString(((Enum<?>) value).name());
                } else if (CharSequence.class.isAssignableFrom(getter.getReturnType())) {
                    generator.writeString((String) value);
                } else {
                    generator.writeString(JsonUtils.toJson(value));
                }
            }

        }
        generator.writeEndObject();
    }
}